#include "SimpleElementS.h"
#include "ImprovedMI.h"
#include "matrix.h"

#include <iostream>

using std::cout;
using std::endl;

ImprovedMI::ImprovedMI(size_t littleDimen, size_t bigDimen, const Matrix<Element> &firstLinear, const Matrix<Element> &secondLinear, const Matrix<Element> &firstAffineAdd, const Matrix<Element> &secondAffineAdd, const CryptoPP::Integer &expIndex)
{
	m_FirstLinear = firstLinear;
	m_FirstAffineAdd = firstAffineAdd;
	m_SecondLinear = secondLinear;
	m_SecondAffineAdd = secondAffineAdd;
	m_ExpIndex = expIndex;

	m_PubKeyEquationGroup.applyExp(m_ExpIndex);
}

void ImprovedMI::encrypt(const std::vector<Element> &plain, std::vector<Element> &cipher) const
{
	Matrix<Element> mPlain(plain.size(), 1);
	for (size_t i = 0; i < plain.size(); i++)
	{
		mPlain(i,0) = plain[i];
	}

	mPlain = m_FirstLinear * mPlain;

	mPlain += m_FirstAffineAdd;


	std::vector<Element> tmpVec;
	tmpVec.resize(plain.size());
	for (size_t i = 0; i < plain.size(); i++)
	{
		tmpVec[i] = mPlain(i,0);
	}



	m_PubKeyEquationGroup.encrypt(tmpVec, cipher);


	for (size_t i = 0; i < cipher.size(); i++)
	{
		if(!cipher[i].isZero())
			cipher[i] = SimpleElementS(1) / cipher[i];
	}


	for (size_t i = 0; i < cipher.size(); i++)
	{
		mPlain(i,0) = cipher[i];
	}

	mPlain = m_SecondLinear * mPlain;
	mPlain += m_SecondAffineAdd;


	for (size_t i = 0; i < cipher.size(); i++)
	{
		cipher[i] = mPlain(i,0);
	}
}

void ImprovedMI::decrypt(const std::vector<Element> &cipher, std::vector<Element> &plain) const
{

}